/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package client.gui.controls.scrabble;

import client.gui.controls.kleurschema.Kleurenschemas;
import client.controllers.ScrabbleController;
import client.controllers.DragAndDropVerifier;
import client.data.BlokjeTransferable;
import javax.swing.*;
import java.awt.*;
import java.awt.dnd.*;
import java.awt.datatransfer.*;
import org.apache.log4j.Logger;
import client.communication.ClientCommunication;

/**
 *
 * @author Liesbeth
 */
public class Vakje extends JLabel {

    public boolean isEnableDrop() {
        return enableDrop;
    }

    public void setEnableDrop(boolean enableDrop) {
        this.enableDrop = enableDrop;
    }

    public enum Type {

        DRIE_MAAL_WOORDWAARDE, TWEE_MAAL_WOORDWAARDE,
        DRIE_MAAL_LETTERWAARDE, TWEE_MAAL_LETTERWAARDE,
        NORMAAL, MIDDEN
    }
    private Logger logger = Logger.getLogger(Vakje.class);
    private ScrabbleController moController;
    private boolean mbBezet,  mbGevalideerd;
    private Type meType;
    private DropTarget dropTarget;
    private DropTargetListener dtListener;
    private Color mcDefaultSelectionColor = new Color(153, 204, 255);
    private int acceptableActions = DnDConstants.ACTION_MOVE;
    private boolean enableDrop = true;

    public Vakje(Type type) {
        this.setType(type);
        this.setForeground(new java.awt.Color(0, 0, 0));
        this.setOpaque(true);
        this.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
        this.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        this.setFont(new java.awt.Font("Arial", 1, 9));
        bepaalLayout();
        this.dtListener = new DTListener();
        this.addComponentListener(new java.awt.event.ComponentAdapter() {

            public void componentResized(java.awt.event.ComponentEvent evt) {
                int fontSize = (int) (Vakje.this.getWidth() / 4.3);
                Vakje.this.setFont(new java.awt.Font("Arial", Font.BOLD, fontSize));
            }
        });

        //Parameters: component, aanvaarde acties, listener, aanvaarden drop
        this.dropTarget = new DropTarget(this,this.acceptableActions, this.dtListener, true);
    }

    public boolean isBezet() {
        return mbBezet;
    }

    public void setBezet(boolean bBezet) {
        this.mbBezet = bBezet;
    }
    

    public boolean isGevalideerd() {
        return mbGevalideerd;
    }

    public void setGevalideerd(boolean bGevalideerd) {
        this.mbGevalideerd = bGevalideerd;
    }

    public Type getType() {
        return meType;
    }

    public void setType(Type eType) {
        this.meType = eType;
    }

    public ScrabbleController getScrabbleController() {
        return moController;
    }

    public void setScrabbleController(ScrabbleController oController) {
        this.moController = oController;
    }

    //Een listener die de status van de Drag en Drop operatie volgt
    class DTListener implements DropTargetListener {

        //Wordt opgeroepen door isDragOk
        //Gaat na of de gekozen dragflavor mag aanvaard worden
        private boolean isDragFlavorSupported(DropTargetDragEvent e) {
            if (e.isDataFlavorSupported(BlokjeTransferable.localStringFlavor)) {
                return true;
            } else {
                return false;
            }
        }

        //Wordt opgeroepen door drop
        //Controleert de flavors en operaties
        private DataFlavor chooseDropFlavor(DropTargetDropEvent e) {
            if (e.isLocalTransfer() && e.isDataFlavorSupported(BlokjeTransferable.localStringFlavor)) {
                return BlokjeTransferable.localStringFlavor;
            }

            if (e.isDataFlavorSupported(BlokjeTransferable.localStringFlavor)) {
                return BlokjeTransferable.localStringFlavor;
            }

            return null;
        }

        //Wordt opgeroepen door dragEnter and dragOver
        //Controleert de flavors en operaties
        private boolean isDragOk(DropTargetDragEvent e) {
            if (isDragFlavorSupported(e) == false) {
                logger.debug("isDragOk: Geen flavor gekozen!");
                return false;
            }

            int da = e.getDropAction();
            logger.debug("Inkomende drop action: " + da);
            logger.debug("Vakje's aanvaarde drop acties: " + acceptableActions);

            if ((da & Vakje.this.acceptableActions) == 0 || Vakje.this.enableDrop==false) {
                return false;
            } else {
                return true;
            }
        }

        //acceptDrag of rejectDrag oproepen adhv isDragOk
        public void dragEnter(DropTargetDragEvent e) {
            if (isDragOk(e) == false) {
                logger.debug("dragEnter: Op dit vakje droppen mag niet!");
                Vakje.this.setBackground(Color.red);
                e.rejectDrag();
            } else {
                Vakje.this.setBackground(mcDefaultSelectionColor);
                logger.debug("dragEnter: aanvaarden van actie " + e.getDropAction());
                e.acceptDrag(e.getDropAction());
            }
        }

        //acceptDrag of rejectDrag oproepen adhv isDragOk
        public void dragOver(DropTargetDragEvent e) {
            if (isDragOk(e) == false) {
                logger.debug("dragOver: Op dit vakje droppen mag niet!");
                Vakje.this.setBackground(Color.RED);
                e.rejectDrag();
            } else {
                logger.debug("dragOver: aanvaarden van actie " + e.getDropAction());
                e.acceptDrag(e.getDropAction());
            }
        }

        public void dropActionChanged(DropTargetDragEvent e) {
        }

        public void dragExit(DropTargetEvent e) {
            logger.debug("Vakje dragExit opgeroepen.");
            bepaalLayout();
        }

        /**
         * perform action from getSourceActions on
         * the transferrable
         * invoke acceptDrop or rejectDrop
         * invoke dropComplete
         * if its a local (same JVM) transfer, use BlokjeTransferable.localStringFlavor
         * find a match for the flavor
         * check the operation
         * get the transferable according to the chosen flavor
         * do the transfer
         */
        public void drop(DropTargetDropEvent e) {
            DataFlavor chosen = chooseDropFlavor(e);
            if (chosen == null || Vakje.this.enableDrop==false) {
                logger.debug("Geen data flavor gekozen voor droppen!");
                e.rejectDrop();
                e.dropComplete(false);
            } else {
                logger.debug("Gekozen data flavor is: " + chosen.getMimeType());

                // De gekozen dropactie
                int da = e.getDropAction();

                // De door dropsource gespecifieerde acties met DragGestureRecognizer
                int sa = e.getSourceActions();
                logger.debug("Drop: sourceActions: " + sa);
                logger.debug("Drop: dropAction: " + da);

                if ((sa & Vakje.this.acceptableActions) == 0) {
                    logger.debug("Foute drop actie!");
                    e.rejectDrop();
                    bepaalLayout();
                    return;
                }

                Object data = null;
                try {
                    //De source listener ontvangt deze actie in dragDropEnd.
                    //Als de actie DnDConstants.ACTION_COPY_OR_MOVE is,
                    //ontvangt de source MOVE!
                    e.acceptDrop(Vakje.this.acceptableActions);

                    data = e.getTransferable().getTransferData(chosen);
                    if (data == null) {
                        throw new NullPointerException();
                    }

                    logger.debug("Binnengekregen data via droppen: " + data.getClass().getName());

                    if (data instanceof Blokje) {
                        //Het blokje op het spelbord plaatsen
                        Blokje b = (Blokje) data;
                        Hokje vp = (Hokje) Vakje.this.getParent();
                        vp.setVakjeOfBlokje(b);
                        Point nieuwePositie;
                        if (!(vp.getParent() instanceof Plankje)) {
                            //Enkel een bezet vakje toevoegen als je dropt op het spelbord
                            //en niet op het plankje
                            ScrabbleController.getInstance().addBezetVakje(vp);
                            nieuwePositie = vp.getLocatie();
                        } else {
                            //wanneer een blokje naar het plankje teruggesleept wordt
                            //geen positie meegeven, bij de nadere clients, moet dit blokje dan gewoon van het spelbord verwijdeerd worden.
                            nieuwePositie = new Point(-1, -1);
                        }
                        //wanneer je een blokje verlegt op het spelbord, moeten de andere spelers dit ook te zien krijgen
                        String gameNaam = ClientCommunication.getInstance().getGameNaam();
                        ClientCommunication.getInstance().verplaatsBlokjeOpSpelbord(nieuwePositie, b.getOldPosition(), b.getLetter(), b.isBlancoBlokje(), gameNaam);
                        e.dropComplete(true);
                        DragAndDropVerifier.getInstance().setDropOpVakje(true);
                        bepaalLayout();
                    } else {
                        e.dropComplete(false);
                        bepaalLayout();
                    }
                } catch (Exception ex) {
                    logger.error("Fout bij het ophalen van de transfer data!");
                    logger.error(ex.getMessage());
                    e.dropComplete(false);
                    bepaalLayout();
                }
            }
        }
    }

    public void bepaalLayout() {
        switch (this.getType()) {
            case NORMAAL:
                // groen
                this.setBackground(new java.awt.Color(0, 153, 153));
                this.setBackground(Kleurenschemas.getInstance().spelbordKleur);
                this.setForeground(Kleurenschemas.getInstance().fontSpelbordKleur);
                break;
            case DRIE_MAAL_WOORDWAARDE:
                //rood
                //this.setBackground(new java.awt.Color(255, 0, 0));
                this.setBackground(Kleurenschemas.getInstance().ww3Kleur);
                this.setForeground(Kleurenschemas.getInstance().fontSpelbordKleur);
                this.setText("<html><center>3X<center><center>WOORD</center><center>WAARDE</center></html>");
                
                break;
            case TWEE_MAAL_WOORDWAARDE:
                //oranje
                //this.setBackground(new java.awt.Color(204, 153, 255));
                this.setBackground(Kleurenschemas.getInstance().ww2Kleur);
                this.setForeground(Kleurenschemas.getInstance().fontSpelbordKleur);
                //this.setBackground(new java.awt.Color(255, 153, 102));
                this.setText("<html><center>2X<center><center>WOORD</center><center>WAARDE</center></html>");
                break;
            case DRIE_MAAL_LETTERWAARDE:
                //donkerblauw
                this.setBackground(Kleurenschemas.getInstance().lw3Kleur);
                this.setForeground(Kleurenschemas.getInstance().fontSpelbordKleur);
                //this.setBackground(new java.awt.Color(0, 102, 255));
                this.setText("<html><center>3X<center><center>LETTER</center><center>WAARDE</center></html>");
                break;
            case TWEE_MAAL_LETTERWAARDE:
                //lichtblauw
                //this.setBackground(new java.awt.Color(153, 204, 255));
                //this.setBackground(new java.awt.Color(51, 255, 153));
                this.setBackground(Kleurenschemas.getInstance().lw2Kleur);
                this.setForeground(Kleurenschemas.getInstance().fontSpelbordKleur);
                this.setText("<html><center>2X<center><center>LETTER</center><center>WAARDE</center></html>");
                break;
            case MIDDEN:
                this.setBackground(Kleurenschemas.getInstance().MiddenKleur);
                this.setForeground(Kleurenschemas.getInstance().fontSpelbordKleur);
               // this.setBackground(new java.awt.Color(255, 255, 102));
                this.setIcon(new ImageIcon(getClass().getResource("/client/gui/star.gif")));
                //this.setBackground(new java.awt.Color(255, 153, 102));
                //this.setText("<html><center><span style='font-size:20px;'>*</span></center></html>");
                break;
        }
    }
}
